package com.wirelesspienetwork.overview.views;

import com.wirelesspienetwork.overview.misc.OverviewConfiguration;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.Component;
import ohos.agp.components.StackLayout;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.AttrSet;
import ohos.agp.render.Canvas;
import ohos.agp.utils.LayoutAlignment;
import ohos.app.Context;

/* A task view */
public class OverviewCard extends StackLayout implements Component.DrawTask {

    OverviewConfiguration mConfig;

    float mTaskProgress;
    AnimatorValue mTaskProgressAnimator;
    DirectionalLayout mContentContainer;
    Component mContent;

    // Optimizations
    AnimatorValue.ValueUpdateListener mUpdateDimListener = (animatorValue, v) -> setTaskProgress(v);

    public OverviewCard(Context context) {
        super(context);
        init(context);
    }

    public OverviewCard(Context context, AttrSet attrs) {
        super(context, attrs);
        init(context);
    }

    public OverviewCard(Context context, AttrSet attrs, int defStyleAttr) {
        super(context, attrs, "");
        init(context);
    }

    private void init(Context context) {
        mContentContainer = new DirectionalLayout(context);
        mContentContainer.setOrientation(DirectionalLayout.VERTICAL);
        LayoutConfig params = new LayoutConfig(LayoutConfig.MATCH_CONTENT, LayoutConfig.MATCH_CONTENT);
        params.alignment = LayoutAlignment.HORIZONTAL_CENTER | LayoutAlignment.TOP;
        mContentContainer.setLayoutConfig(params);
        addComponent(mContentContainer);
        addDrawTask(this);
    }

    public void setConfig(OverviewConfiguration config)
    {
        mConfig = config;
    }

    public void setContent(Component content) {
        mContent = content;
        mContentContainer.removeAllComponents();
        if (mContent != null) {
            mContentContainer.addComponent(mContent);
        }
        setTaskProgress(getTaskProgress());
    }

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int width = EstimateSpec.getSize(widthMeasureSpec);
        int height = EstimateSpec.getSize(heightMeasureSpec);
        int widthWithoutPadding = width - getPaddingLeft() - getPaddingRight();
        int heightWithoutPadding = height - getPaddingTop() - getPaddingBottom();

        // Measure the content
        mContentContainer.estimateSize(EstimateSpec.getSizeWithMode(widthWithoutPadding, EstimateSpec.PRECISE),
                EstimateSpec.getSizeWithMode(heightWithoutPadding, EstimateSpec.PRECISE));

        setEstimatedSize(width, height);
    }

    /** Synchronizes this view's properties with the task's transform
     * @param toTransform
     * @param duration*/
    void updateViewPropertiesToCardTransform(OverviewCardTransform toTransform, int duration) {
        updateViewPropertiesToCardTransform(toTransform, duration, null);
    }

    void updateViewPropertiesToCardTransform(OverviewCardTransform toTransform, int duration,
                                             AnimatorValue.ValueUpdateListener updateCallback) {
        // Apply the transform
        toTransform.applyToTaskView(this, duration, mConfig.fastOutSlowInInterpolator, false,
                true, updateCallback);

        // Update the task progress
        if (mTaskProgressAnimator != null) {
            mTaskProgressAnimator.release();
            mTaskProgressAnimator.cancel();
        }
        if (duration <= 0) {
            setTaskProgress(toTransform.p);
        } else {
            mTaskProgressAnimator = new AnimatorValue();
            mTaskProgressAnimator.setDuration(duration);
            mTaskProgressAnimator.setValueUpdateListener(mUpdateDimListener);
            mTaskProgressAnimator.start();
        }
    }

    /** Resets this view's properties */
    void resetViewProperties() {
        OverviewCardTransform.reset(this);
    }

    /** Prepares this task view for the enter-recents animations.  This is called earlier in the
     * first layout because the actual animation into recents may take a long time. */
    void prepareEnterRecentsAnimation() {
    }

    /** Animates this task view as it enters recents
     * @param ctx */
    void startEnterRecentsAnimation(final ViewAnimation.OverviewCardEnterContext ctx) {
        final OverviewCardTransform transform = ctx.currentTaskTransform;

        // Animate the tasks up
        int frontIndex = (ctx.currentStackViewCount - ctx.currentStackViewIndex - 1);
        int duration = Math.max(0, mConfig.taskViewEnterFromHomeDuration +
                frontIndex * mConfig.taskViewEnterFromHomeStaggerDelay);

        int delay =  Math.max(0, mConfig.taskViewEnterFromHomeDelay -
                frontIndex * mConfig.taskViewEnterFromHomeStaggerDelay);

        setScaleX(transform.scale);
        setScaleY(transform.scale);
        new AnimatorProperty()
                .moveToY(transform.translationY)
                .setDelay(delay)
                .setCurveType(mConfig.quintOutInterpolator)
                .setDuration(duration)
                .setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {

            }

            @Override
            public void onStop(Animator animator) {

            }

            @Override
            public void onCancel(Animator animator) {

            }

            @Override
            public void onEnd(Animator animator) {
                ctx.postAnimationTrigger.decrement();
            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        }).start();

        ctx.postAnimationTrigger.increment();
    }

    /** Sets the current task progress.
     * @param p */
    public void setTaskProgress(float p) {
        mTaskProgress = p;
    }

    /** Returns the current task progress.
     * @return float */
    public float getTaskProgress() {
        return mTaskProgress;
    }

    /** Enables/disables handling touch on this task view.
     * @param enabled */
    void setTouchEnabled(boolean enabled) {
        setClickedListener(!enabled ? null : (ClickedListener) v -> {

        });
    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        onMeasure(getWidth(),getHeight());
    }
}
